﻿//-----------------------------------------------------------------------
// <copyright file="IconObjectFactory.cs" company="Redmist">
//     Copyright (c) Damien T Smith. All rights reserved.
// </copyright>
// <author>Damien Smith</author>
//-----------------------------------------------------------------------

namespace Redmist.UsageMonitor.IconCreation
{
    using System;
    using System.Drawing;
    using System.Drawing.Text;

    /// <summary>Contains methods for constructing a percentage icon.</summary>
    public static class IconObjectFactory
    {
        /// <summary>The proportion of the icon used for the remaining percentage text background.</summary>
        private const float BackgroundProportion = 0.84f;

        /// <summary>The ratio of font size to background area height for a one or two digit percentage.</summary>
        private const float TwoDigitSizeRatio = 0.8f;

        /// <summary>The ratio of font size to background area height for a three digit percentage.</summary>
        private const float ThreeDigitSizeRatio = 0.56f;

        /// <summary>The offset proportion of the text shadow relative to the font size</summary>
        private const int ShadowProportion = 16;

        /// <summary>The maximum icon width where cleartype is used for rendering the icon text.</summary>
        private const int ClearTypeThreshold = 32;

        /// <summary>Creates a centered string format for centering text on the icon.</summary>
        /// <returns>A System.Drawing.StringFormat representing text layout information.</returns>
        public static StringFormat CreateIconStringFormat()
        {
            return new StringFormat()
                {
                    LineAlignment = StringAlignment.Center,
                    Alignment = StringAlignment.Center
                };
        }

        /// <summary>Creates a rectangle in the lower portion of a bitmap where the background and text will be drawn.</summary>
        /// <param name="iconBitmap">A System.Drawing.Bitmap representing the source bitmap.</param>
        /// <returns>A System.Drawing.Rectangle representing the background area of the icon.</returns>
        public static Rectangle CreateBackgroundRectangle(Bitmap iconBitmap)
        {
            int height = Convert.ToInt32(iconBitmap.Height * BackgroundProportion);
            int width = iconBitmap.Width;
            return new Rectangle(0, iconBitmap.Height - height, width, height);
        }

        /// <summary>Creates a rectangle in the upper portion of a bitmap where the status color will be drawn.</summary>
        /// <param name="backRectangle">A System.Drawing.Rectangle representing the lower portion of a drawing surface.</param>
        /// <returns>A System.Drawing.Rectangle representing the status area of the icon.</returns>
        public static Rectangle CreateStatusRectangle(Rectangle backRectangle)
        {
            int height = backRectangle.Y;
            int width = backRectangle.Width;
            return new Rectangle(0, 0, width, height);
        }

        /// <summary>Creates a graphics surface used for drawing an icon.</summary>
        /// <param name="bitmap">A System.Drawing.Bitmap used as the base image for the icon.</param>
        /// <param name="clearType">Indicates whether ClearType should be used for rendering text on the icon if appropriate.</param>
        /// <returns>A Redmist.UsageMonitor.IconCreation.IGraphics representing a drawing surface for creating an icon.</returns>
        public static IGraphics CreateGraphics(Bitmap bitmap, bool clearType)
        {
            IGraphics graphics = new IconGraphics(Graphics.FromImage(bitmap));

            if (clearType && bitmap.Width < ClearTypeThreshold)
            {
                graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
            }
            else
            {
                graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
            }

            return graphics;
        }

        /// <summary>Determines the center point of a rectangle.</summary>
        /// <param name="rectangle">A System.Drawing.RectangleF representing the source rectangle.</param>
        /// <returns>A System.Drawing.PointF representing the center of the rectangle.</returns>
        public static PointF CreateCenterPoint(RectangleF rectangle)
        {
            float x = (int)(rectangle.Width / 2) + rectangle.X;
            float y = (int)(rectangle.Height / 2) + rectangle.Y;
            return new PointF(x, y);
        }

        /// <summary>Creates a font based on the current system default font at the specified pixel size.</summary>
        /// <param name="fontPixelSize">The pixel size of the font.</param>
        /// <returns>A System.Drawing.Font based on the current system default font at the specified pixel size.</returns>
        public static Font CreateIconFont(float fontPixelSize)
        {
            return new Font(SystemFonts.DefaultFont.FontFamily, fontPixelSize, FontStyle.Regular, GraphicsUnit.Pixel);
        }

        /// <summary>Determines the font size to be used for the icon based on the number of digits in the percent text.</summary>
        /// <param name="textDigits">The length (number of digits) in the percentage text.</param>
        /// <param name="height">The height of the area used as a background for the text.</param>
        /// <returns>The pixel size to be used for the font.</returns>
        public static float CalculateFontSize(int textDigits, int height)
        {
            float fontSize;
            if (textDigits == 3)
            {
                fontSize = height * ThreeDigitSizeRatio;
            }
            else
            {
                fontSize = height * TwoDigitSizeRatio;
            }

            return fontSize;
        }

        /// <summary>Determines the center point for the percent text shadow based on the size of the font.</summary>
        /// <param name="textCenter">A System.Drawing.PointF representing the center of the foreground text.</param>
        /// <param name="fontSize">The size of the font in pixels.</param>
        /// <returns>A System.Drawing.PointF representing the center of the shadow text.</returns>
        public static PointF CreateShadowCenterPoint(PointF textCenter, float fontSize)
        {
            float shadowOffset = fontSize / ShadowProportion;
            return new PointF(textCenter.X += shadowOffset, textCenter.Y += shadowOffset); 
        }
    }
}
